#include "utils/oss_client_manager.hpp"
#include "common/config.hpp"
#include <iostream>

std::unique_ptr<OssClientManager> OssClientManager::m_instance = nullptr;

OssClientManager::OssClientManager() {
    // 在init中进行初始化
}

OssClientManager* OssClientManager::getInstance() {
    if (m_instance == nullptr) {
        m_instance = std::unique_ptr<OssClientManager>(new OssClientManager());
    }
    return m_instance.get();
}

void OssClientManager::init() {
    // 初始化网络资源
    AlibabaCloud::OSS::InitializeSdk();

    const char* accessKeyId_env = std::getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    const char* accessKeySecret_env = std::getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

    if (accessKeyId_env == nullptr || accessKeySecret_env == nullptr) {
        std::cerr << "Error: OSS Access Key environment variables not set." << std::endl;
        // 在实际应用中，这里可能需要更复杂的错误处理，比如抛出异常
        return;
    }

    // 从Config类获取配置信息
    AlibabaCloud::OSS::ClientConfiguration conf;
    m_client = std::make_unique<AlibabaCloud::OSS::OssClient>(
        Config::OSS_ENDPOINT,
        accessKeyId_env,
        accessKeySecret_env,
        conf
    );
}

OssClientManager::~OssClientManager() {
    // 释放网络资源
    AlibabaCloud::OSS::ShutdownSdk();
}

// 上传文件
bool OssClientManager::uploadFile(const std::string& objectKey, const std::string& content) {
    auto stream = std::make_shared<std::stringstream>(content);
    AlibabaCloud::OSS::PutObjectRequest request(Config::OSS_BUCKET_NAME, objectKey, stream);

    auto outcome = m_client->PutObject(request);

    if (!outcome.isSuccess()) {
        std::cerr << "PutObject fail,"
            << " code:" << outcome.error().Code()
            << ", message:" << outcome.error().Message()
            << ", requestId:" << outcome.error().RequestId() << std::endl;
        return false;
    }
    return true;
}

// 下载文件
std::shared_ptr<std::iostream> OssClientManager::downloadFile(const std::string& objectKey) {
    auto outcome = m_client->GetObject(Config::OSS_BUCKET_NAME, objectKey);

    if (!outcome.isSuccess()) {
        std::cerr << "GetObject fail,"
            << " code:" << outcome.error().Code()
            << ", message:" << outcome.error().Message()
            << ", requestId:" << outcome.error().RequestId() << std::endl;
        return nullptr;
    }
    return outcome.result().Content();
}
